Premiers pas en WebScraping
Introduction à la collecte automatique de données du Web
Cet article peut être utilisé pour une initiation aux bases de la collecte automatique de données du Web avec R. De nombreux aspects et méthodes de webscraping qui ne sont pas abordés dans ce document sont présenté sur ce site web associé plus complet et approfondie sur le webscraping avec R et Python.
Introduction
Le web scraping, ou extraction de données sur le web, est une technique qui consiste à extraire de manière automatisée des informations à partir de sites web. En d’autres termes, c’est comme si vous utilisiez un robot pour récupérer des données à partir de pages web, plutôt que de le faire manuellement.
En sciences humaines et sociales, le web scraping peut être utilisé pour collecter des données pertinentes sur des sites web, forums, blogs, des réseaux sociaux, ou autres sources en ligne. Cette méthode peut être particulièrement utile pour analyser des tendances, des opinions, des dynamiques, ou tout simplement pour constituer une base de données à partir de plusieurs sources web. L’utilisation de R pour le web scraping permet d’automatiser ces processus et d’analyser les données extraites de manière efficace.
Le Web scraping permet d’extraire des informations spécifiques d’une page web en analysant sa structure HTML et en extrayant uniquement les éléments pertinents. Cette pratique demande ainsi quelques connaissances techniques en matière de web, de langage de balisage HTML et de langage CSS, qui permettent respectivement de structurer une page web et de définir l’apparence et la mise en forme des différents éléments du document.
Au delà de présenter le web scraping avec R, cet article aborde dans un premier temps les connaisances indispensables à la mise en place d’une collecte de données automatisée.
Le Web scraping regroupe différentes techniques plus ou moins complexes. Cet article, qui est une inititation à la pratique de la collecte automatique de données présente le cas d’utilisation le plus simple. Pour aller plus loin et se former à des techniques plus avancées, vous pouvez consulter ce support de formation plus détaillé :
1 Bases techniques
L’extraction automatisée de données du web requiert des prérequis indispensables : certaines connaissances spécifiques liées à la structure d’une page web et une compréhension des principes techniques sous-jacents. Vous devez ainsi acquérir une connaissance du langage HTML (balises) et une familiarité avec le CSS (sélecteurs) pour identifier, cibler et extraire les éléments d’une page web.
1.1 Le langage HTML
Le langage HTML (HyperText Markup Language) est un dérivé du XML (eXtensible Markup Language). Le XML est un langage de balisage flexible qui permet de définir des règles spécifiques pour structurer et stocker des données. Il est utilisé dans une variété de domaines, notamment pour l’échange de données entre applications. Par exemple, voici un document XML simple représentant des informations sur un livre :
<Book>
<Title>Le Seigneur des Anneaux</Title>
<Author>J.R.R. Tolkien</Author>
<Genre>Fantasy</Genre>
<Year>1954</Year>
</Book>
Le langage HTML, sous-langage du XML, partage de nombreuses caractéristiques avec ce langage, mais il est spécifiquement conçu pour structurer et organiser le contenu des pages web. Le HTML utilise une série de balises (tags) pour définir la structure et le contenu d’une page web, ce qui permet aux navigateurs web de l’afficher correctement pour les utilisateurs.
1.1.1 Les balises
Il n’y a pas de nombre fixe de balises HTML, car de nouvelles balises peuvent être introduites avec les versions futures du langage HTML. Cependant, il existe un ensemble de balises HTML standard définies dans les spécifications du W3C (World Wide Web Consortium1). Pour obtenir la liste la plus à jour des balises HTML, vous pouvez consulter la documentation officielle du W3C.
Chaque balise est entourée des symboles
< et >
et peut contenir des attributs qui spécifient des propriétés
supplémentaires pour l’élément. Si aucune balise n’est obligatoire dans
une page HTML, il est de convention d’avoir la structure de base
suivante :
<!DOCTYPE html>
<html>
<head>
<title>Titre de la page</title>
</head>
<body>
<!-- Contenu de la page -->
</body>
</html><!DOCTYPE html>: En début du document, indique au navigateur qu’il s’agit d’une page HTML52.<html>: Englobe tout le contenu de la page HTML. Définit le début et la fin du document HTML.<head>: Contient les métadonnées de la page, des liens vers des fichiers annexes (CSS, javascript…), etc.<title>: Définit le titre de la page qui apparaîtra dans la barre de titre du navigateur.<body>: Contient tout le contenu visible de la page, tel que le texte, les images, les liens, les tableaux, etc.
Dans la majorité des cas, on utilise une balise de fermeture pour
indiquer la fin de l’élémént. Une balise de fermeture présente un
/ avant le nom de la balise :
Le body peut contenir toute une variété de balises prédéfinies pour structurer et ajouter différents types de contenu dans la page web. Voici quelques balises indispensables à connaitre :
<h1>,<h2>, …,<h6>: titres de différents niveaux,
<p>: paragraphe,
<a>: lien hypertexte,
<img>: image,
<ul>,<ol>,<li>: listes non ordonnées et ordonnées,
<table>,<tr>,<td>: tableau avec des lignes et des cellules,
<div>: section (type bloc),
<span>: section (type “inline”).
Exemple d’utilisation de la balise p
(paragraphe) :
Dans cet exemple, les balises <p>
et </p> permettent de créer un
paragraphe dont le contenu textuel est “Ceci est un paragraphe en
langage HTML”.
Les différentes balises permettent ainsi de structurer, hierarchiser et organiser le contenu d’une page web. Elles peuvent s’emboiter indéfiniment :
<body>
<div>
<p>Un paragraphe en <a href="https://fr.wikipedia.org/wiki/HTML5">langage HTML</a></p>
</div>
</body>Voici le rendu graphique du code HTMl ci-dessus dans un naviguateur web :
1.1.2 Les attributs
Ces balises hiérarchisées et potentiellement regroupées, peuvent être renseignées d’attributs qui permettent de spécifier des informations supplémentaires et jouer sur leur mise en forme. Par exemple :
id: identifiants,
class: classes,
href: liens,
- etc.
Ces attributs sont à spécifier dans les balises ouvrantes :
<body>
<div id="debut_doc">
<h1 class="categorie">Tous les articles</h1>
</div>
<div id="Liste_ref">
<h2 class="article">Titre article</h2>
<p class="summary">Résumé de l'article...</p>
<a href="https://www.article.org">Intégralité de l'article</a>
<h2 class="article">Titre article bis</h2>
<p class="summary">Résumé de l'article bis...</p>
<a href="https://www.article_bis.org">Intégralité de l'article bis</a>
</div>
</body>L’organisation segmentée du contenu via les balises
div ou span
ainsi que les différents attributs spécifiés permettent la mise en forme
et le paramétrage des éléments. Les attributs des balises peuvent être
associés à une mise en forme (couleur, taille, position, etc.) à l’aide
du langage CSS (cf. partie suivante). Mais
il s’agit également d’éléments cruciaux pour la collecte
automatisée de données sur le web, car il permettent de cibler
précisément des éléments.
Dans l’exemple ci-dessus, il est ainsi possible de récupérer toutes
les URLs (Uniform Resource
Locator) des articles en ciblant le contenu de tous les
attributs href des balises
<a> situés dans les
<div> ayant pour identifiant
“Liste_ref”…
1.2 Le langage CSS
Le CSS, ou Cascading Style Sheets (feuilles de style en cascade), est un langage de programmation utilisé pour décrire l’apparence et la mise en forme des documents HTML et XML. Il permet de contrôler l’apparence visuelle des différents éléments de pages web (taille, position, couleur, police, marges, etc.) via les sélecteurs CSS.
Le CSS peut être incorporé de différentes manières :
1. Directement dans les balises à l’aide de
l’attribut style :
2. Dans le document HTML, via la balise
<style> adaptée à cet effet :
<style>
h1 {
color: #f03b35;
font-size: 40px;
text-align: center;
}
</style>
<body>
<h1>Titre principal</h1>
</body>3. Dans une feuille de style externe (fichier texte
avec l’extension .css). Cette dernière
méthode est à privilégier car la séparation du contenu et la mise en
forme facilite la mise à jour des styles :
Dans les trois cas, le rendu graphique dans un naviguateur web sera le suivant :
1.2.1 Les sélecteurs CSS simples
Plusieurs sélecteurs CSS permettent de cibler et styliser les différentes balises HTML :
1. Les sélecteurs d’éléments permettent de cibler tous les éléments d’un même type.
2. Les sélecteurs d’identifiants permettent de
cibler un élément spécifique par son identifiant
(id).
3. Les sélecteurs de classes permettent de cibler
les éléments ayant une classe spécifique
(class).
4. Les sélecteurs d’attributs permettent de cibler
les éléments ayant un attribut spécifique. Exemple : l’attribut
href (lien cliquable)
Il est possible de préciser sa cible en indiquant une valeur pour l’attribut.
1.2.2 Les sélecteurs complexes et combinateurs
Le CSS met également à disposition des sélecteurs complexes et combinateurs que l’on peut utiliser pour cibler des contenus de manière très précise. Quelques exemples :
A. Les sélecteurs descendants ciblent les éléments, descendants d’un autre élément.
B. Les sélecteurs de voisin direct ciblent les nœuds qui suivent immédiatement un élément.
1.2.3 Exemple pratique
Pour mieux comprendre l’utilisation et le fonctionnement du HTML et du CSS, vous pouvez vous exercer à la pratique de ces deux langages à partir de cet exemple simple mis à disposition en téléchargement :
Une fois téléchargé, décompressez le répertoire qui contient deux fichiers : page.hmtl et style.CSS.
- Un fichier HTML peut être interprété (mis en page) par n’importe quel navigateur (Firefox, Google Chrome, Microsoft Edge, ect…). Ouvrez le fichier page.html avec un naviguateur. Aucune connexion internet n’est nécessaire.
- Ouvrez les deux fichiers (page.hmtl et style.CSS) avec un editeur de fichier texte (ex : bloc-note, Rstudio, Notepad++…).
<!DOCTYPE html>
<html>
<head>
<title>Ma Page HTML</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Un titre de niveau 1</h1>
<p>Un premier petit paragraphe.</p>
<h2>Un titre de niveau 2</h2>
<p>Un autre paragraphe contenant un lien pour aller sur le site
<a href="https://elementr.netlify.app/">d'ElementR</a>.
</p>
</body>
</html>Ajoutez et/ou modifiez du contenu (balise) dans le code source du fichier page.html. Enregistrez le fichier et réaffichez (ou raffraichissez avec la touche
F5) la page HTML dans le naviguateur pour apprécier la nouvelle mise en page.Ajoutez et/ou modifiez du contenu dans le code source du fichier style.css. Enregistrez le fichier et réaffichez la page HTML (ou raffraichissez la avec la touche
F5) dans le naviguateur pour apprécier la nouvelle mise en page.
1.3 Le code source d’une page
La connaissance du HTML et du CSS vous permettra de comprendre et de naviguer dans le code source du page web. L’ensemble des navigateurs web modernes proposent des outils d’inspection du code source des pages web.
L’inspecteur de code source permet d’explorer le code source d’une page web. Il permet l’identification des balises, des classes, des identifiants et des styles associés aux éléments, et ainsi de procéder à une extraction ciblée de données. En utilisant l’inspecteur de code source, vous accédez à toutes les informations nécessaires pour concevoir un script de collecte automatisée.
Pour y accéder, cliquez-droit n’importe où sur la page web ouverte dans un naviguateur, puis cliquez sur “Inspecter” :
Avec Google Chrome :
Avec Mozilla FireFox :
L’inspecteur s’ouvre et en utilisant l’outil de sélection (entouré en rouge), il donne la possibilité de naviguer dans le code source en survolant les différents éléments de la page, et vice versa.
Vous pouvez déplier le code source pour l’explorer en profondeur. Cet
article est une page HTML dans laquelle l’ensemble de la partie “2.
Bases techniques” semblent contenu dans une div ayant
pour identifiant "bases-techniques" :
En réalisant un clic-droit sur un élément, vous pouvez récupérer plusieurs choses. Cliquez sur copier :
Il est ainsi possible de récupérer aisément :
- l’intérieur du HTML : contenu de la balise
sélectionnée. Par exemple, l’intérieur du HTML de
<div id="abc" class="foo"><strong>TEXTE</strong></div>est<strong>TEXTE</strong>) - l’exterieur du HTML : ensemble de la balise
sélectionnée. Par exemple, l’extérieur du HTML de
<div id="abc" class="foo"><strong>TEXTE</strong></div>est<div id="abc" class="foo"><strong>TEXTE</strong></div>) - Le sélecteur CSS (ex :
#bases-techniques) - Le chemin CSS (ex :
html body.preload div#content div#main div#bases-techniques.section.level1 - Le Xpath (ex :
//*[@id="bases-techniques"])
Ces trois derniers éléments pourront vous être précieux pour
automatiser votre collecte. Par exemple, le sélecteur CSS
#bases-techniques h2 permet de cibler tous les titres de
niveau 2 présents dans l’élément div ayant pour identifiant
“bases-techniques”.
1.4 Les appels réseaux d’une page
Quand on souhaite réaliser une collecte d’éléments redondants (structurés de la même manière) sur une page web (ex: sites d’annonce, catalogues de médias, etc.), il peut être utile de chercher à comprendre le fonctionnement interne de la page.
Pour cela, il est possible d’observer ce qui se passe lorsqu’une page web est chargée, de manière à essayer de repérer des éléments structurés (données json par exemple) qui seraient chargées ou requêtées lors de l’interrogation de la page. Il s’agit donc d’observer les appels qu’une page émet lors de son chargement, pour par récupérer des images, des polices, des bibliothèques de mise en page (CSS, javascript), etc…
On peut réaliser cette opération dans l’inspecteur de code, dans l’onglet “Réseaux” (ou Network dans Chrome) après avoir actualisé la page :
Dans L’exemple ci-dessus, on constate que l’ouverture de la page de cet article déclenche :
- L’ouverture de la page à proprement parler (format
htmldans la colonneType).
- Le chargement de la bibliothèque de fonctions MathJax.js
(
javascript) qui permettent de mettre en forme des équations dans des pages HTML.
- La tentative de chargement de la “favicon” du site, c’est-à-dire de l’icône qui devrait s’afficher dans le titre de l’onglet. Comme cette icône n’existe pas, la page essaie de la charger depuis d’autres emplacements (3 derniers appels), sans succès.
2 Présentation du cas pratique
2.1 Le site web ScrapImmob
Pour cette introduction au web scraping avec R, nous proposons une mise en pratique sur un site web de démonstration crée pour l’occasion : ScrapImmob. Ce site compile 1000 annonces fictives de ventes immobilères de maisons et d’appartements.
Comme n’importe quel site d’annonces immobilières, ScapImmob recense des annonces de ventes de maisons ou d’appartements dans dix départements français : l’Essonne, l’Eure, les Hauts-de-Seine, Paris, la Seine-Maritime, la Seine-Saint-Denis, la Seine-et-Marne, le Val d’Oise, le Val de Marne et les Yvelines.
Une exploration rapide du site nous permet d’observer que chaque annonce contient les informations suivantes :
- des photographies,
- un titre,
- une description,
- des caractèristiques techniques (surfaces, prix, nombre de pièces,
etc.),
- Une localisation (commune et carte interactive).
Pour automatiser la collecte de ces informations, nous devons inspecter le code source du site pour déterminer la localisation précise de ces différents éléments. Dans quelles balises se trouvent-il ? Quels sont les identifiants ou classes des différentes balises ? ect.
2.2 Exploration du code source
Pour scrapper, il est important de comprendre comment le site web est construit pour être capacité de cibler les bons élements. Après avoir navigué sur ScrapImmob de manière classique, nous pouvons commencer à explorer son code source. Pour cela, nous allons utiliser l’inspecteur de code pour comprendre comment les éléments sont organisés dans la page et détécter les noms de balises, de classes, d’identifiants et les styles associés aux différents éléments..
2.3 Défintion des objectifs
Avant de se lancer dans une collecte automatisée, il est primordiale de bien définir ses objectifs et de déterminer précisément quelles informations on souhaite récupérer. L’exploration du code source nous permettra ensuite d’estimer le niveau de difficulté et de choisir une méthode optimisée.
Pour cette introduction, notre objectif est de récupérer une partie de la base de données (un département) des biens mis en vente sur ScrapImmob, incluant l’ensemble des caractèristiques de description. La récupération des coordonnées géographiques affichées dans la carte intéractive est également souhaitée.
Pour répondre a cet objectif, le processus de collecte va se dérouler en plusieurs étapes :
Comprendre la structure de la page centrale (ou page d’acceuil).
Comprendre le système d’URL du site afin de pouvoir cibler la collecte sur une catégorie (département et type).
Trouver où récupérer les URLs de chaque page d’annonce ciblée, puis les collecter.
Comprendre la structure des pages d’annonces et localiser les informations à récupérer dans le code source.
Collecter l’ensemble des caractèristiques de chaque bien à partir de la liste des URL récupérées.
Collecter les coordonnées géographiques affichées dans la carte interactive pour tous les biens ciblés.
3 Mise en pratique
3.1 Les packages de scraping
Comme pour toutes les opérations et manipulations de données, plusieurs solutions existent pour le scraping avec le langage R. Si plusieurs fonctions R-base peuvent être utilisées, il existe surtout deux packages R de référence en matière de collecte automatisée :
rvest: développé par Hadley Wickham (Rstudio), ce package facilite le scraping en utilisant les sélecteurs CSS et XPath pour extraire les données formatées en HTML ou en XML. Ce package s’insprire de bibliothèques python déjà existantes : Beautiful Soup et RoboBrowser.rvestfait partie de l’écosystèmetidyverse, les fonctions peuvent s’utiliser avec le(s) pipe(s). Ce package est simple d’utilisation mais également limité en matière de fonctionnalité. Il ne permet pas de simuler des actions d’un utilisateur (clic, scroll…). On l’utilisera essentiellement pour l’extraction de données de sites web statiques bien structurée.Rselenium: ce package est ce qu l’on appelle un binding de langage (“liaison”) qui permet d’utiliser les fonctionnalités deSelenium 2.0 WebDriver. Ce framework web permet d’automatiser les tests d’applications Web en simulant des utilisateurs.Selenium 2.0 WebDriverpeut aussi être utilisé pour la collecte automatisée de données sur des sites web dynamiques, nécessitant une interaction utilisateur (exécution de code javascript généré par clic, survol, scroll…).
Le site web ScrapImmob
est un site web statique. Il n’existe pas de base de données, toutes les
informations affichées sont présentes dans le code source de la page. Il
n’est donc pas necessaire de simuler le comportement d’un utilisateur
pour accéder aux données ciblées. Dans ce cas, il sera donc plus
simple d’utiliser le package rvest.
3.2 Le package
rvest
3.2.1 Installation
Le package rvest**
permet de naviguer à travers la structure HTML des pages web, extraire
du texte, des tableaux, des images et d’autres éléments, et les
convertir en données structurées directement exploitables dans R.
Pour le besoin de l’exercice, nous allons aussi utiliser les packages :
purrpour manipuler des données en utilisant des fonctions de programmation fonctionnelle.tibblepour manipuler les données tabulaires.dplyrpour manipuler les données.stringrpour manipuler les chaînes de caractères.ggplot2pour faire des graphiques.tmpour l’analyse statistique de textes.wordcloudpour faire un nuage de mots.leafletpour faire une carte interactive.
Installez les packages, puis chargez la librairie.
#Installation des packages
install.packages("rvest")
install.package("purrr")
install.package("tibble")
install.package("dplyr")
install.package("stringr")
install.packages("ggplot2")
install.packages("tm")
install.packages("wordcloud")
install.packages("leaflet")
#Chargement des librairies
library(rvest)
library(purrr)
library(tibble)
library(dplyr)
library(stringr)
library(ggplot2)
library(tm)
library(wordcloud)
library(leaflet)3.2.2 Mode de fonctionnement
Commençons par explorer les principales fonctions du package rvest**
à partir d’un extrait du code source du site web ScrapImmob.
Pour cela, nous pouvons utiliser la fonction
minimal_html() qui permet de créer un
contenu HTML (XML) requêtable à partir d’un contenu HTML fourni dans une
chaîne de caractère.
# Extrait de code source html du site ScrapImmob
extrait_html <- "<div class='card-body'>
<a href='annonces/IDF_0078.html' class='stretched-link'></a>
<p class='card-text'>Maison charmante de 96 m² avec grand jardin à Châtenay-Malabry</p>
</div>"
# Interprétation du "texte" comme du code source html
basic_html <- minimal_html(extrait_html)
class(basic_html)[1] "xml_document" "xml_node"
- Les fonctions
read_element()ouread_elements()permettent respectivement la récupération du 1er ou de tous les élements d’un document HTML, en précisant un sélécteur CSS ou un Xpath.
{xml_nodeset (1)}
[1] <p class="card-text">Maison charmante de 96 m² avec grand jardin à Châten ...
- La fonction
html_attr()permet l’extraction des valeurs d’attributs.
# Récupérer le ou les URL(s) indiquée(s) dans l'attribut href
basic_html %>% html_elements("a") %>% html_attr("href")[1] "annonces/IDF_0078.html"
- Les fonctions
html_text()ouhtml_text2()permettent d’extraire uniquement le texte d’un élément.
[1] "Maison charmante de 96 m² avec grand jardin à Châtenay-Malabry"
3.3 Le système d’URL
3.3.1 Filtrage des biens & ciblage d’URL
Sur la page d’acceuil du site ScrapImmob, un ensemble de boutons situé à gauche permet de filtrer les biens par département et par type de biens. Lorsque l’on clique sur l’un de ces bouttons, les biens affichés sur la page sont filtrés en fonction du choix réalisé et l’URL de la page est modifié de la manière suivante :
URL principale :
https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/index.html
URL du filtre “Essonne (91) - Appartement” :
https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/91_appartement/index.html
URL du filtre “Val-d’Oise (95) - Maison” :
https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/95_maison/index.html
Notre objectif étant de collecter uniquement des données sur les biens (maisons et appartemments) de la Seine-Maritime, nous allons cibler bnotre collecte sur les deux URLs suivantes :
- Maisons : https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/index.html
- Appartements : https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/index.html
Commençons par récupérer le code source de ces deux pages à l’aide de
la fonction read_html. Cette fonction effectue une requête
HTTP, puis en analyse le code HTML récupéré à l’aide du package
xml2.
url_appart <- "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/"
url_maison <- "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/"
code_appart <- read_html(url_appart)
code_maison <- read_html(url_maison)
# Affichage de l'objet code_appart
code_appart{html_document}
<html lang="en">
[1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8 ...
[2] <body>\n <div class="container-fluid">\n <div class="row">\n ...
3.3.2 Collecte des URLs des pages d’annonce
A partir de ces deux URLs, nous allons pouvoir récupérer la liste des
URLs de toutes les pages des annonces affichées sur ces pages. Cela nous
permettra dans un second temps, de collecter l’ensemble des informations
de description de chaque bien en vente. Ces URLs sont stockées dans une
balise <a> de la classe *stretched-link*
:
Pour récuperer la liste de ces URLs, nous devons donc cibler les
valeurs de l’attribut href dans toutes les balises de
classe *stretched-link* :
[1] "../annonces/Normandie_0105.html" "../annonces/Normandie_0029.html"
[3] "../annonces/Normandie_0011.html" "../annonces/Normandie_0252.html"
[5] "../annonces/Normandie_0398.html" "../annonces/Normandie_0026.html"
[7] "../annonces/Normandie_0032.html" "../annonces/Normandie_0385.html"
[9] "../annonces/Normandie_0203.html" "../annonces/Normandie_0361.html"
[11] "../annonces/Normandie_0284.html" "../annonces/Normandie_0336.html"
[13] "../annonces/Normandie_0212.html" "../annonces/Normandie_0393.html"
[15] "../annonces/Normandie_0354.html" "../annonces/Normandie_0261.html"
[17] "../annonces/Normandie_0189.html" "../annonces/Normandie_0259.html"
Nous pouvons faire la même chose pour les annonces de vente de maison en Seine-Maritime :
[1] "../annonces/Normandie_0255.html" "../annonces/Normandie_0416.html"
[3] "../annonces/Normandie_0062.html" "../annonces/Normandie_0172.html"
[5] "../annonces/Normandie_0410.html" "../annonces/Normandie_0035.html"
[7] "../annonces/Normandie_0304.html" "../annonces/Normandie_0476.html"
[9] "../annonces/Normandie_0427.html" "../annonces/Normandie_0442.html"
[11] "../annonces/Normandie_0276.html" "../annonces/Normandie_0087.html"
[13] "../annonces/Normandie_0441.html" "../annonces/Normandie_0281.html"
[15] "../annonces/Normandie_0290.html" "../annonces/Normandie_0217.html"
[17] "../annonces/Normandie_0310.html" "../annonces/Normandie_0006.html"
Cela permet uniquement de récupérer les URls des annonces affichées sur la première page. Pour collecter l’ensemble des biens ciblés, nous devons comprendre comment fonctionne le système d’URL qui permet d’afficher les différentes pages…
3.3.3 Nombre de page & liste d’URLs
Nous avons pu collecter les URLs des biens affichés sur la première page. Pour reproduire la collecte d’URLs sur l’ensemble des pages des appartements et des maisons de Seine-Maritime, il est necéssaire de connaitre le nombre de page affichables et de comprendre le système d’URLs.
Dans cette section, il y a 156 biens en vente, et chaque page en affiche jusqu’à 18. Il y a donc 9 pages des biens listés à collecter (156 / 18 = 8.7).
Dans cette section, il y a 263 biens en vente, et chaque page en affiche jusqu’à 18. Il y a donc 15 pages des biens listés à collecter (263 / 18 = 14.6).
Losrque l’on observe le comportement de l’URL à chauqe chargement d’une nouvelle page, il est facile de comprendre le système d’URLs utilisé par ScrapImmob, exemple :
Page 1 = https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/index.html
Page 2 = https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_2.html
Page 3 = https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_3.html
…
Page 9 = https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_9.html
Ainsi, il est simple de reconstituer la liste des URLs de pages ciblées :
# Nombres de pages à scrapper
nbpage_appart <- 9
nbpage_maison <- 15
# Création de vecteurs avec l'URL de la première page
list_url_appart <- paste0(url_appart, "index.html")
list_url_maison <- paste0(url_maison, "index.html")
# Affichage
list_url_appart[1] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/index.html"
Nous utilisons ensuite une boucle pour reconstituer la liste des URLs à scrapper :
# Récupération des URLs pour les biens de type "appartement" (76)
list_url_appart[2:nbpage_appart] <- paste0(url_appart, "page_", 2:nbpage_appart,".html")
# Récupération des URLs pour les biens de type "maison" (76)
list_url_maison[2:nbpage_maison] <- paste0(url_maison, "page_", 2:nbpage_maison,".html")
# Concaténation des deux vecteurs
list_url <- c(list_url_appart, list_url_maison)
# Affichage
print(list_url) [1] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/index.html"
[2] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_2.html"
[3] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_3.html"
[4] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_4.html"
[5] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_5.html"
[6] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_6.html"
[7] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_7.html"
[8] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_8.html"
[9] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_appartement/page_9.html"
[10] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/index.html"
[11] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_2.html"
[12] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_3.html"
[13] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_4.html"
[14] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_5.html"
[15] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_6.html"
[16] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_7.html"
[17] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_8.html"
[18] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_9.html"
[19] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_10.html"
[20] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_11.html"
[21] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_12.html"
[22] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_13.html"
[23] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_14.html"
[24] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/76_maison/page_15.html"
rselenium nous aurait permis
de simuler un clic d’utilisateur sur le bouton “page suivante”,
et ainsi de collecter les informations de l’ensemble des pages sans se
soucier du système d’URL. Cette étape n’aurait pas été nécéssaire.
3.3.4 Scraping des URLs de tous les biens ciblés
Nous avons maintenant tous les élements donc nous avons besoin pour collecter les URLs des biens de la Seine-Maritime.
# Création d'un vecteur vide
liens <- character()
# Boucle de récupération des URLs de page d'annonce
for (i in 1:length(list_url)){
# Récupération du code source de la page
page <- read_html(list_url[i])
# Récupération du lien dans les balises de la classe "stretched-link"
liens[i] <- page %>% html_elements(".stretched-link") %>% html_attr("href")
}
print(liens) [1] "../annonces/Normandie_0105.html" "../annonces/Normandie_0445.html"
[3] "../annonces/Normandie_0095.html" "../annonces/Normandie_0359.html"
[5] "../annonces/Normandie_0298.html" "../annonces/Normandie_0271.html"
[7] "../annonces/Normandie_0282.html" "../annonces/Normandie_0331.html"
[9] "../annonces/Normandie_0091.html" "../annonces/Normandie_0255.html"
[11] "../annonces/Normandie_0464.html" "../annonces/Normandie_0034.html"
[13] "../annonces/Normandie_0326.html" "../annonces/Normandie_0478.html"
[15] "../annonces/Normandie_0315.html" "../annonces/Normandie_0408.html"
[17] "../annonces/Normandie_0008.html" "../annonces/Normandie_0169.html"
[19] "../annonces/Normandie_0142.html" "../annonces/Normandie_0439.html"
[21] "../annonces/Normandie_0296.html" "../annonces/Normandie_0110.html"
[23] "../annonces/Normandie_0418.html" "../annonces/Normandie_0069.html"
Les URLs récupérées semblent relatives (uniquement la fin), nous
allons donc reconstituer les URLs à l’aide de la fonction
gsub() :
liens <- gsub(x = liens,
pattern = "..",
replacement = "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob",
fixed = TRUE)
print(liens) [1] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0105.html"
[2] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0445.html"
[3] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0095.html"
[4] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0359.html"
[5] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0298.html"
[6] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0271.html"
[7] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0282.html"
[8] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0331.html"
[9] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0091.html"
[10] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0255.html"
[11] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0464.html"
[12] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0034.html"
[13] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0326.html"
[14] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0478.html"
[15] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0315.html"
[16] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0408.html"
[17] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0008.html"
[18] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0169.html"
[19] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0142.html"
[20] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0439.html"
[21] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0296.html"
[22] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0110.html"
[23] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0418.html"
[24] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0069.html"
#Fonction pour récupérer les url des biens immobiliers
extraire_liens <- function(url) {
page <- read_html(url)
liens <- page %>% html_elements("div:nth-child(1) > div:nth-child(3) > a:nth-child(1)") %>% html_attr("href")
return(liens)
}
# Liste pour stocker tous les liens
liste_de_liens <- list()
#Stocker les liens de la première page des appartements
liens_page <- extraire_liens(url_appart)
liste_de_liens <- c(liste_de_liens, liens_page)
#Boucle pour les appartements
for (i in 2:nbpage_appart) {
url_page <- paste0(url_appart, "page_", i,".html")
liens_page <- extraire_liens(url_page)
# Stocker les liens obtenus
liste_de_liens <- c(liste_de_liens, liens_page)
}
#Stocker les liens de la première page des maisons
liens_page <- extraire_liens(url_maison)
liste_de_liens <- c(liste_de_liens, liens_page)
#Boucle pour les maisons
for (i in 2:nbpage_maison) {
url_page <- paste0(url_maison, "page_", i,".html")
liens_page <- extraire_liens(url_page)
# Stocker les liens obtenus
liste_de_liens <- c(liste_de_liens, liens_page)
}
#Transformer en lien absolu
for (i in 1:length(liste_de_liens)){
lientemp <- url_absolute(liste_de_liens[[i]], "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/a/b")
liste_de_liens[[i]] <- lientemp
}
#Afficher l'URL du premier bien récupéré
liste_de_liens[[1]][1] "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/annonces/Normandie_0105.html"
3.3.5 Scraping d’éléments d’une page d’annonce immobilière
Notre liste de page web a scrapper est prête. Nous pouvons maintenant explorer les pages de chaque annonce pour comprendre comment sont structurées les données en HTML pour afin de les extraire automatiquement.
Après exploration avec l’inspecteur de code, nous observons que les éléments ciblés sont stockés dans les balises suivantes :
- Titre court : Balise
<h6>de classedisplay-6 - Titre long : Balise
<h5>de classecard-title - Description : Balise
<p>de classecard-text text-start
Les autres informations sont stockées dans une même balise
<ul> (liste) de classe list-group :
- Type de bien : Balise
<h6>de classecard-text text-start - Nombre de chambre
- Nb de salle de bain
- Surface habitable
- Prix
La récupération de la localisation du marqueur dans la carte intéractive est un peu plus complexe. Nous les récupérerons dans un second temps.
#Récupérer l'URL de la 1ère annonce
urlannonce1 <- liste_de_liens[[1]]
#Lire la page
pageannonce1 <- read_html(urlannonce1)
#Récupérer l'élément titre
pageannonce1 %>% html_element(".display-6") %>% html_text2()[1] "Appartement charmeux de 57m² à Elbeuf - Région Normandie à vendre à 90000€"
Affichons la 1ère image de l’un des biens
#Récupérer de l'URL de la 1ère image
image_url <- pageannonce1 %>%
html_element("img") %>% # Sélectionner tous les éléments 'img'
html_attr("src")
image_url <- url_absolute(image_url, "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/a/b")
3.4 Scraping de la base de données de la Seine-Maritime
3.4.1 Fonctions nécessaires au scraping
Nous allons créer un ensemble de fonction qui nous permettent de scrapper les différents élements des annonces de la Seine-Maritime.
#Fonction d'extraction du titre court
extraire_titrec <- function(page) {
titre <- page %>% html_element(".display-6") %>% html_text2()
return(titre)
}
#Fonction d'extraction du titre long
extraire_titrel <- function(page) {
element <- page %>% html_element("h5.card-title:nth-child(1)") %>% html_text2()
return(element)
}
#Fonction d'extraction de la description
extraire_description <- function(page) {
element <- page %>% html_element(".card-text") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 1 du tableau
extr_att1 <- function(page) {
element <- page %>% html_element("ul.list-group > li:nth-child(1) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 2 du tableau
extr_att2 <- function(page) {
element <- page %>% html_element("ul.list-group > li:nth-child(2) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 3 du tableau
extr_att3 <- function(page) {
element <- page %>% html_element("li.list-group-item:nth-child(3) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 4 du tableau
extr_att4 <- function(page) {
element <- page %>% html_element("li.list-group-item:nth-child(4) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 5 du tableau
extr_att5 <- function(page) {
element <- page %>% html_element("li.list-group-item:nth-child(5) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de l'attribut 6 du tableau
extr_att6 <- function(page) {
element <- page %>% html_element("li.list-group-item:nth-child(6) > strong:nth-child(2)") %>% html_text2()
return(element)
}
#Fonction d'extraction de la commune
extraire_commune <- function(page) {
element <- page %>% html_element("div.list-group:nth-child(1) > li:nth-child(1) > strong:nth-child(1)") %>% html_text2()
return(element)
}
#Fonction d'extraction du département
extraire_departement <- function(page) {
element <- page %>% html_element("div.list-group:nth-child(1) > li:nth-child(2) > strong:nth-child(1)") %>% html_text2()
return(element)
}
#Fonction d'extraction de la localisation
extraire_loc <- function(page){
element <-
page %>% html_elements('script') %>% # On récupère les balises de type script
html_text2() %>% # On en extrait le contenu
pluck(2) %>% # On ne garde que la 2ème balise string, qui est celle qui contient le code leaflet
str_extract(string = .,
pattern = "var annonce_coords = \\[(\\d+\\.?\\d*\\, \\d+\\.?\\d*)\\]", # regexp qui cherche les caractères "var annonce_coords = [unNombreDecimal, unAutreNombreDecimal]" et met les deux nombres décimaux dans un groupe (les parenthèses) -> "49.224678, 1.184296"
group = 1) %>% # On ne conserve que le groupe 1, donc ce qui était en parenthèse dans la regexp
str_split(pattern = ',') %>% # On découpe par la virgule -> list(c("49.224678", " 1.184296"))
pluck(1) %>% # str_split crée une liste de vecteurs, on ne garde que le premier élément -> c("49.224678", " 1.184296")
str_trim() %>% # sur chaque vecteur, on enlève les espaces en début et en fin -> c("49.224678", "1.184296")
as.numeric() # On peut enfin les convertir en numérique, et donc récupérer la latitude puis la longitude (ordre inversé de coordonnées de leaflet)
return(element)
}
extraire_img <- function(page) {
element <- page %>% html_element("img") %>% # Sélectionner tous les éléments 'img'
html_attr("src")
element <- url_absolute( element, "https://analytics.huma-num.fr/Robin.Cura/ScrapImmob/a/b")
return(element)
}3.4.2 Scraping de la base
Appliquons maintenant les fonctions à la liste de biens pour
constituer notre base de données. Nous pourrions effectuer une boucle
comme nous l’avons fait précédemment avec les URL afin de montrer une
autre méthode nous allons utiliser la fonction map_df du
package purrr. Elle permet d’appliquer des
fonctions à chaque élement d’une liste et de combiner les résultats en
un unique tableau de données.
#Scrapping de la base de données
db_bien <- map_df(liste_de_liens , ~{
paste(.)
page <- read_html(.)
tibble (lien = .,
titrecourt = extraire_titrec(page),
titrelong = extraire_titrel(page),
description = extraire_description(page),
type = extr_att1(page),
nb_chambres = extr_att2(page),
nb_sb = extr_att3(page),
surf_h = extr_att4(page),
surf_j = case_when(!is.na(extr_att6(page))~ extr_att5(page), .default = NA_character_), #l'attribut surface jardin n'est pas toujours présent.
prix = case_when(!is.na(extr_att6(page))~ extr_att6(page), .default = extr_att5(page)),
commune = extraire_commune(page),
departement = extraire_departement(page),
lien_img = extraire_img(page),
latitude = extraire_loc(page)[1],
longitude = extraire_loc(page)[2]
)
})
#Nettoyage de la base de données
db_bien <- db_bien %>% mutate(identifiant = row_number(), #ajout d'un identifiant
nb_chambres = as.numeric(nb_chambres), #nombre de chambres en numérique
nb_sb = as.numeric(nb_sb), #nombre de salle de bain en numérique
surf_h=as.numeric(str_remove(surf_h,"m²")), #enlever le symbole m2 et transformation en numérique
surf_j = as.numeric(str_remove(surf_j,"m²")), #enlever le symbole m2 et transformation en numérique
prix = as.numeric(str_remove_all(prix,"€| ")), #enlever le symbole € et les espaces puis transformation en numérique
libcom = substr(commune, 1, nchar(commune) - 8), #enlever le code INSEE pour garder que le nom de commune
code_insee = substr(commune, nchar(commune)-5, nchar(commune)-1) #enlever le nom de commune que le code insee
) %>%
select(- commune ) #Supprimer le champs commune3.5 Exploration de la base de données scrappées
3.5.1 Présentation de la BD scrapée
Notre base de données scrappées contient les 419 biens à vendre en Seine-Maritime avec les attributs suivants :
lien, l’URL pour accèder en ligne au bientitrecourt, le titre court de l’annoncetitrelong, le titre long de l’annoncedescription, la description complète de l’annoncetype, le type de bien (maison ou appartement)nb_chambres, le nombre de chambresnb_sb, le nombre de salles de bainsurface_h, la surface habitable (en m2)surface_j, la surface de jardin (en m2)prix, le prix (en €)departement, le département dans lequel le bien se situelien_img, l’URL de la 1ère image de l’annoncelatitude, la latitudelongitude, la longitudeidentifiant, un identifiant uniquelibcom, le nom de la communecode_insee, le code insee
3.5.2 Répartition par type
ggplot(db_bien) +
aes(x = type) +
geom_bar(fill = "#4682B4") +
labs(y = "Nombre de biens", title = "Répartition du nombre de biens selon le type") +
coord_flip() +
theme_gray() +
theme(plot.title = element_text(size = 14L, face = "bold"))3.5.3 Distribution par type/prix
ggplot(db_bien) +
aes(x = type, y = prix) +
geom_boxplot(fill = "#4682B4") +
geom_jitter() +
labs(y = "Prix des biens",
title = "Répartition selon le prix des biens") +
theme_gray() +
theme(plot.title = element_text(size = 14L,
face = "bold"))
### Surface moyenne
ggplot(db_bien) +
aes(x = type, y = surf_h, color=type) +
geom_boxplot() +
geom_jitter() +
labs(y = "Surface en m2",
title = "Répartition selon le prix des biens") +
theme_gray() +
theme(plot.title = element_text(size = 14L,
face = "bold"))3.5.4 Nuage de mot sur les description des biens
# Création du corpus
corpus <- Corpus(VectorSource(db_bien$description))
# Prétraitement du texte
corpus <- tm_map(corpus, content_transformer(tolower))
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeNumbers)
corpus <- tm_map(corpus, removeWords, stopwords("french"))
# Création du nuage de mots
wordcloud(corpus, scale=c(3,0.5), max.words=50, random.order=FALSE, colors=brewer.pal(8, "Dark2"))3.5.5 Carte !
# Créer la carte Leaflet
carte <- leaflet(db_bien) %>%
addTiles() %>%
addCircleMarkers(lng = ~longitude,
lat = ~latitude,
popup = ~paste("<strong>", titrecourt, "</strong>",
"<br><img src='",lien_img,"' style='width:200px;height:200px;'>",
"<br><strong>Type :</strong>", type,
"<br><strong>Surface habitable :</strong>",surf_h,"m²",
"<br><strong>Nombre de chambres :</strong>",nb_chambres, "</strong>",
"<br><strong>Nombre de salles de bains :</strong>", nb_sb,"</strong>",
"<br><strong>Prix :</strong>",prix,"€"
),
label = ~titrecourt,
radius = 1,
color = ~ifelse(type == "Appartement", "#0C3762", "#F0AA0C"),
fillOpacity = 0.8)
#Afficher la carte
carteGéocodage adresse + carto
3.5.6 Export
3.5.6.1 csv
3.5.6.2 Géopackage
4 Conclusion
Ouverture Le bon coin ?
Bibliographie
Annexes
Info session
| setting | value |
|---|---|
| version | R version 4.4.0 (2024-04-24) |
| os | Ubuntu 22.04.4 LTS |
| system | x86_64, linux-gnu |
| ui | X11 |
| language | (EN) |
| collate | fr_FR.UTF-8 |
| ctype | fr_FR.UTF-8 |
| tz | Europe/Paris |
| date | 2024-05-15 |
| pandoc | 3.1.11 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/x86_64/ (via rmarkdown) |
| package | ondiskversion | source |
|---|---|---|
| dplyr | 1.1.4 | CRAN (R 4.4.0) |
| DT | 0.33 | CRAN (R 4.4.0) |
| ggplot2 | 3.5.1 | CRAN (R 4.4.0) |
| leaflet | 2.2.2 | CRAN (R 4.4.0) |
| NLP | 0.2.1 | CRAN (R 4.4.0) |
| purrr | 1.0.2 | CRAN (R 4.4.0) |
| RColorBrewer | 1.1.3 | CRAN (R 4.4.0) |
| rvest | 1.0.4 | CRAN (R 4.4.0) |
| stringr | 1.5.1 | CRAN (R 4.4.0) |
| tibble | 3.2.1 | CRAN (R 4.4.0) |
| tm | 0.7.13 | CRAN (R 4.4.0) |
| wordcloud | 2.6 | CRAN (R 4.4.0) |
Citation
Auteur.e P, Auteur.e S (2021). “Titre de la fiche.” doi:10.48645/xxxxxx, https://doi.org/10.48645/xxxxxx,, https://rzine.fr/publication_rzine/xxxxxxx/.
BibTex :
@Misc{,
title = {Titre de la fiche},
subtitle = {Sous-Titre de la fiche},
author = {Premier Auteur.e and Second Auteur.e},
doi = {10.48645/xxxxxx},
url = {https://rzine.fr/publication_rzine/xxxxxxx/},
keywords = {FOS: Other social sciences},
language = {fr},
publisher = {FR2007 CIST},
year = {2021},
copyright = {Creative Commons Attribution Share Alike 4.0 International},
}
Glossaire
Le World Wide Web Consortium, abrégé par le sigle W3C, est un organisme de standardisation à but non lucratif, fondé en octobre 1994 chargé de promouvoir la compatibilité des technologies du World Wide Web telles que HTML5, HTML, XHTML, XML, RDF, SPARQL, CSS, XSL, PNG, SVG, MathML et SOAP.↩︎
HTML5 (HyperText Markup Language 5) est la dernière révision majeure du HTML (format de données conçu pour représenter les pages web). Cette version a été finalisée le 28 octobre 2014. HTML5 spécifie deux syntaxes d’un modèle abstrait défini en termes de DOM : HTML5 et XHTML5.↩︎